/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-07-03 08:41:35
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-07-06 16:58:53
 * @FilePath: /lesson/lesson_net/cal_server(http demo and serialize)/TcpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <functional>
#include "Socket.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace socket_ns;

static const int gport = 8888;

using service_t = std::function<std::string(std::string &requeststr)>;

class TcpServer
{

public:
    TcpServer(service_t service,int port=gport)
    :_port(port)
    ,_listensock(std::make_shared<TcpSocket>())
    ,_isrunning(false)
    ,_service(service)
    {
        _listensock->BuildListenSocket(_port);
    }

    class ThreadData
    {
        public:
        SockSPtr _sockfd;
        TcpServer *_self;
        InetAddr _addr;
        public:
        ThreadData(SockSPtr sockfd, TcpServer *self, const InetAddr &addr):_sockfd(sockfd), _self(self), _addr(addr)
        {}
    };


    static void* Execute(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td=static_cast<ThreadData *>(args);
        
        td->_self->_service(td->_sockfd,td->_addr);
        td->_sockfd->Close();
        delete td;
        return nullptr;
    }
    
    void Loop()
    {
        _isrunning=true;
        while(_isrunning)
        {
            InetAddr client;
            SockSPtr newsock=_listensock->Accepter(&client);
            if(newsock==nullptr) continue;

            LOG(INFO, "get a new link, client info : %s, sockfd is : %d\n", client.AddrStr().c_str(), newsock->Sockfd());

            pthread_t tid;
            ThreadData *td = new ThreadData(newsock, this, client);
            pthread_create(&tid, nullptr, Execute, td); // 新线程进行分离
        }
        _isrunning=false;
    }

    ~TcpServer()
    {

    }

private:
    uint16_t _port;
    SockSPtr _listensock;
    bool _isrunning;
    service_t _service;
};